//
//  DWRuntime.m
//  OCAPPDemo
//
//  Created by 杨冬武 on 2022/9/18.
//

#import "DWRuntime.h"
#import "DWRuntimeDog.h"
#import <objc/runtime.h>

@implementation DWRuntime

- (void)otherTest {
    NSLog(@"%s", __FUNCTION__);
}

+ (void)otherTest {
    NSLog(@"%s", __FUNCTION__);
}


/// 实例方法解析
/// @param sel 消息选择器
+ (BOOL)resolveInstanceMethod:(SEL)sel {
    if (sel == @selector(test)) {
        // 添加新的方法 将otherTest添加给test
        Method m = class_getInstanceMethod(self, @selector(otherTest));
        class_addMethod(self, sel, method_getImplementation(m), method_getTypeEncoding(m));
        return YES;
    }
    return [super resolveInstanceMethod:sel];
}

/// 类方法解析
/// @param sel 消息选择器
//+ (BOOL)resolveClassMethod:(SEL)sel {
//
//    if (sel == @selector(classTest)) {
//        // 添加新的方法 将otherTest添加给test
//        Method m = class_getClassMethod(self, @selector(otherTest));
//        class_addMethod(object_getClass(self), sel, method_getImplementation(m), method_getTypeEncoding(m));
//        return YES;
//    }
//
//    return [super resolveClassMethod:sel];
//}


/// 快速消息转发 (指定一个实例对象)
/// @param aSelector 消息选择器
//- (id)forwardingTargetForSelector:(SEL)aSelector {
//
//    if (aSelector == @selector(test)) {
//        // 类方法需要指定类对象
//        return [[DWRuntimeDog alloc] init];
//    }
//
//    return [super forwardingTargetForSelector:aSelector];
//}

/// 快速消息转发 (指定一个类对象)
/// @param aSelector 消息选择器
//+ (id)forwardingTargetForSelector:(SEL)aSelector {
//
//    if (aSelector == @selector(classTest)) {
//        // 类方法需要指定类对象
//        return [DWRuntimeDog class];
//    }
//
//    return [super forwardingTargetForSelector:aSelector];
//}



/// 指定方法签名
/// @param aSelector 消息选择器
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector {
    if (aSelector == @selector(test)) {
        return [NSMethodSignature signatureWithObjCTypes:"v16@0:8"];
    } else if (aSelector == @selector(classTest)) {
        return [NSMethodSignature signatureWithObjCTypes:"v16@0:8"];
    }
    return [super methodSignatureForSelector:aSelector];
}


/// 转发调用
/// @param anInvocation 方法调用(方法调用者receiver, SEL, 方法参数arguments, 方法返回值returnValue)
- (void)forwardInvocation:(NSInvocation *)anInvocation {
    NSLog(@"%s", __FUNCTION__);
    
    // 获取参数
    id a;
    SEL b;
    [anInvocation getArgument:&a atIndex:0];
    [anInvocation getArgument:&b atIndex:1];
    NSLog(@"%@, %s", a, b);
    
    // 获取target
    NSLog(@"%@", anInvocation.target);
    
    // 获取返回值
    // 如果获取返回值 NSMethodSignature需要有对应的返回值
    //    id r;
    //    [anInvocation getReturnValue:&r];
    //    NSLog(@"%@", r);
    
    // 如果直接调用 invoke会导致死循环
    // [anInvocation invoke];
    
    // 可以指定其他对象调用
    //    anInvocation.target = [[DWRuntimeDog alloc] init];
    //    [anInvocation invoke];
    [anInvocation invokeWithTarget:[DWRuntimeDog new]];
    
}


/// 快速消息转发 (指定一个实例对象)
/// @param aSelector 消息选择器
+ (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector {
    if (aSelector == @selector(classTest)) {
        return [NSMethodSignature signatureWithObjCTypes:"v16@0:8"];
    }
    return [super methodSignatureForSelector:aSelector];
}

+ (void)forwardInvocation:(NSInvocation *)anInvocation {
    
    // 获取参数
    id a;
    SEL b;
    [anInvocation getArgument:&a atIndex:0];
    [anInvocation getArgument:&b atIndex:1];
    NSLog(@"%@, %s", a, b);
    
    // 获取target
    NSLog(@"%@", anInvocation.target);
    
    // 获取返回值
    // 如果获取返回值 NSMethodSignature需要有对应的返回值
    //    id r;
    //    [anInvocation getReturnValue:&r];
    //    NSLog(@"%@", r);
    
    // 如果直接调用 invoke会导致死循环
    // [anInvocation invoke];
    
    // 可以指定其他对象调用
    //    anInvocation.target = [DWRuntimeDog class];
    //    [anInvocation invoke];
    [anInvocation invokeWithTarget:[DWRuntimeDog class]];
    
}


@end
